
package cn.donting.jme.expansion.tool;

import cn.donting.jme.EditorContent;
import cn.donting.jme.JmeApplication;
import cn.donting.jme.event.camera.CameraTransformChangeEvent;
import cn.donting.jme.event.spatial.SpatialTransformChangeEvent;
import cn.donting.jme.expansion.tool.transform.Axis;
import cn.donting.jme.expansion.tool.transform.TransformSceneTool;
import cn.donting.jme.ioc.Bean;
import cn.donting.jme.ioc.BeanInitialization;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.jme3.asset.AssetManager;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;

/**
 * 场景编辑工具
 */
@Slf4j
@Bean
public class TranslationSceneTool extends TransformSceneTool implements BeanInitialization {

    private Spatial translation;

    private Node xAxis;
    private Node yAxis;
    private Node zAxis;

    private Vector3f spaPos;

    public TranslationSceneTool() {

    }

    @Override
    public String getName() {
        return "Translation";
    }

    @Override
    public Icon getIcon(int size) {
        return new FlatSVGIcon("icon/addFile.svg", size, size);
    }

    private void initSpatialTranslation(Spatial spatial) {
        if (spatial instanceof Geometry) {
            ((Geometry) spatial).getMaterial().getAdditionalRenderState().setDepthTest(false);
        }
        if (spatial instanceof Node) {
            if (spatial.getName().equals("xAxis")) {
                xAxis = (Node) spatial;
            }
            if (spatial.getName().equals("yAxis")) {
                yAxis = (Node) spatial;
            }
            if (spatial.getName().equals("zAxis")) {
                zAxis = (Node) spatial;
            }
            for (Spatial child : ((Node) spatial).getChildren()) {
                initSpatialTranslation(child);
            }
        }
    }


    @Override
    protected void startMove() {
        if (getSelectSpatial() != null) {
            spaPos = getSelectSpatial().getLocalTranslation().clone();
        } else {
            spaPos = getSelectCamera().getCamera().getLocation().clone();
        }
    }

    protected void move(Axis axis, Vector3f startPos, Vector3f endPos) {
        Vector3f subtract = endPos.subtract(startPos);
        Vector3f dir = new Vector3f();
        float distance = 0;
        switch (axis) {
            case X -> {
                subtract.y = 0;
                subtract.z = 0;
                if (getSelectSpatial() != null) {
                    dir = getSelectSpatial().getLocalRotation().getRotationColumn(0);
                } else {
                    dir = getSelectCamera().getCamera().getRotation().getRotationColumn(0);
                }
                distance = subtract.x;
                //旋转后 改变方向
                if(dir.x<0){
                    distance=-distance;
                }
            }
            case Y -> {
                subtract.x = 0;
                subtract.z = 0;
                if (getSelectSpatial() != null) {
                    dir = getSelectSpatial().getLocalRotation().getRotationColumn(1);
                } else {
                    dir = getSelectCamera().getCamera().getRotation().getRotationColumn(1);
                }
                distance = subtract.y;
                //旋转后 改变方向
                if(dir.y<0){
                    distance=-distance;
                }
            }
            case Z -> {
                subtract.x = 0;
                subtract.y = 0;
                if (getSelectSpatial() != null) {
                    dir = getSelectSpatial().getLocalRotation().getRotationColumn(2);
                } else {
                    dir = getSelectCamera().getCamera().getRotation().getRotationColumn(2);
                }
                distance = subtract.z;
                //旋转后 改变方向
                if(dir.z<0){
                    distance=-distance;
                }
            }
        }
        //某些情况下 distance 会非常大。ray 的 射线检测会出现 distance非常大的情况
        Vector3f add = spaPos.add(dir.mult(distance));
        if (add.equals(Vector3f.ZERO) || Math.abs(distance) > 1000) {
            return;
        }
        if (getSelectSpatial() != null) {
            getSelectSpatial().setLocalTranslation(add);
            SpatialTransformChangeEvent spatialTransformChangeEvent = new SpatialTransformChangeEvent(this, getSelectSpatial());
            EditorContent.postEvent(spatialTransformChangeEvent);
        } else {
            getSelectCamera().getCamera().setLocation(add);
            CameraTransformChangeEvent cameraTransformChangeEvent = new CameraTransformChangeEvent(this, getSelectCamera());
            EditorContent.postEvent(cameraTransformChangeEvent);
        }

    }

    @Override
    protected Spatial xAxis() {
        return xAxis;
    }

    @Override
    protected Spatial yAxis() {
        return yAxis;
    }

    @Override
    protected Spatial zAxis() {
        return zAxis;
    }

    @Override
    public void initialization(JmeApplication application) {
        AssetManager assetManager = application.getAssetManager();
        translation = assetManager.loadModel("tranlation/translation.j3o");
        translation.setLocalTranslation(new Vector3f());
        getToolNode().attachChild(translation);
        initSpatialTranslation(translation);
    }
}
